home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’97 / Threaded Menus / source code / INIT.c next >
Encoding:
C/C++ Source or Header  |  1997-06-27  |  13.8 KB  |  660 lines  |  [TEXT/KAHL]

  1. #include <Events.h>
  2. #include <Resources.h>
  3. #include <Memory.h>
  4. #include <ToolUtils.h>
  5. #include <Menus.h>
  6. #include <LowMem.h>
  7. #include <Traps.h>
  8.  
  9. #define CurMenuID   (*(short *)0xB54)
  10. #define CurMenuItem (*(short *)0xB56)
  11.  
  12. // Need to patch: MenuSelect, WaitMouseUp, 
  13.  
  14. #ifndef powerc
  15.     #ifdef THINK_C
  16.         #pragma parameter __D0 SetA4(__D0)
  17.         pascal long SetA4(long newA4) = 0xC18C;
  18.     
  19.         #define SetCurrentA4() SetA4((long)&main)
  20.     #else
  21.         #include <A4Stuff.h>
  22.     //    #include <SetUpA4.h>
  23.     #endif
  24. #else
  25.     #define SetCurrentA4() 0
  26.     #define SetA4(x) 0
  27.  
  28.     ProcInfoType __procinfo = kCStackBased
  29.              | RESULT_SIZE(kFourByteCode)
  30.              | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(void *)));
  31. #endif
  32.  
  33. pascal long (*gOldMenuSelect)(Point pt);
  34. pascal void (*gOldHiliteMenu)(short);
  35. pascal void (*gOldDrawMenuBar)(void);
  36. pascal void (*gOldJShieldCursor)(short left, short top, short right, short bottom);
  37.  
  38. pascal long myMenuSelect(Point pt);
  39. pascal void myHiliteMenu(short);
  40. pascal void myDrawMenuBar(void);
  41. pascal void myJShieldCursor(short left, short top, short right, short bottom);
  42.  
  43. enum {
  44.     uppMenuSelectProcInfo = kPascalStackBased | RESULT_SIZE(kFourByteCode) | STACK_ROUTINE_PARAMETER(1, kFourByteCode)
  45. };
  46.  
  47.  
  48. pascal short (*gOldWaitMouseUp)(void);
  49.  
  50. pascal short myWaitMouseUp(void);
  51.  
  52. enum {
  53.     uppWaitMouseUpProcInfo = kPascalStackBased | RESULT_SIZE(kTwoByteCode)
  54. };
  55.  
  56. // Globals
  57.  
  58. static void GNEFilterGlue(void);
  59. static void myMenuSelectLoopCode(void);
  60.  
  61.  
  62. static GNEFilterUPP gFilterProc;
  63.  
  64. static Ptr gGNEStack;
  65. static long gGNEPC;
  66. static GrafPtr gGNEPort;
  67. static Ptr gMenuSelectStack;
  68. static long gMenuSelectPC;
  69. static GrafPtr gMenuSelectPort;
  70.  
  71. static Point gMSPoint;
  72. static int gDoSelect = false;
  73.  
  74. static short gHaveFakeMSResult = false;
  75. static long gFakeMSResult;
  76.  
  77. static short gGNEReEntrancy;
  78. static short gInMenuSelect = false;
  79.  
  80. static Handle gMacsBug;
  81.  
  82. enum {
  83.     kStackSize = 1024*24
  84. };
  85.  
  86. void main(void)
  87. {
  88.     long    oldA4;
  89.     THz        oldZone;
  90.  
  91.         // Set up A4, so we can access our globals.
  92.     oldA4 = SetCurrentA4();
  93.  
  94.         // Set the current zone to the system zone.  In the 680x0 case, this
  95.         // is not necessary, but it's not a bad idea and it keeps us out of
  96.         // trouble when traps that we don't expect to have side effects
  97.         // unexpectedlty allocate memory from the current zone.  One example
  98.         // of this is the NewRoutineDescriptor routine.
  99.     oldZone = GetZone();
  100.     SetZone(SystemZone());
  101.  
  102.         // We need to detach our code, so that we stay around.
  103.     DetachResource(GetResource('INIT', 237));
  104.     DetachResource(gMacsBug = Get1Resource('PICT', 237));
  105.     
  106.         // Allocate the stack
  107.         
  108.     gMenuSelectStack = NewPtr(kStackSize) + kStackSize;
  109.     gMenuSelectPC    =  (long) &myMenuSelectLoopCode;
  110.     
  111.         // Remember the old definition of GNEFilter
  112.         
  113.     gFilterProc = LMGetGNEFilter();    
  114.     LMSetGNEFilter((GNEFilterUPP)GNEFilterGlue);
  115.         
  116.     #if 1
  117.  
  118.         // Remember the old implementation of WaitMouseUp and MenuSelect.
  119. //    gOldWaitMouseUp = (void *) GetToolTrapAddress(0xA977);
  120.     gOldMenuSelect = (void *) GetToolTrapAddress(0xA93D);
  121.  
  122.         // Patch ourselves in.
  123. //    SetToolTrapAddress(NewRoutineDescriptor((ProcPtr) &myWaitMouseUp,uppWaitMouseUpProcInfo,kPowerPCISA), 0xA977);
  124.     SetToolTrapAddress(NewRoutineDescriptor((ProcPtr) &myMenuSelect, uppMenuSelectProcInfo,kPowerPCISA), 0xA93D);
  125.     
  126.     gOldHiliteMenu = (void*) GetToolTrapAddress(_HiliteMenu);
  127.     SetToolTrapAddress((ProcPtr) &myHiliteMenu, _HiliteMenu);
  128.     
  129.     gOldDrawMenuBar = (void*) GetToolTrapAddress(_DrawMenuBar);
  130.     SetToolTrapAddress((ProcPtr)&myDrawMenuBar, _DrawMenuBar);
  131.     
  132.     // Path shieldcursor to pick up updates.
  133.     
  134.     gOldJShieldCursor = *(QDJShieldCursorProcPtr*)0x0808;
  135.     *(QDJShieldCursorProcPtr*)0x0808 = myJShieldCursor;
  136.     
  137.     #endif
  138.         // Restore the old zone again
  139.     SetZone(oldZone);
  140.  
  141.         // And restore the value of A4 on the way out.
  142.     SetA4(oldA4);
  143. }
  144.  
  145. static void DoMacsBugThing(EventRecord *erp) {
  146.     char            ASCIIval = (char) erp->message;
  147.     Rect            r, ir;
  148.     WindowPtr        wp;
  149.     WindowRecord    wr;
  150.     EventRecord        xer;
  151.     Rect            gray = GetMainDevice()[0]->gdPMap[0][0].bounds;
  152.     GrafPtr            oldPort;
  153.  
  154.     long oldA4 = SetCurrentA4();
  155.  
  156.     if (gInMenuSelect) {
  157.         GetPort(&oldPort);
  158.         if (ASCIIval == 'Q' || ASCIIval == 'q') {
  159.             if (erp->modifiers & cmdKey) {
  160.                 r.top = (gray.bottom - gray.top - 400) / 2;
  161.                 r.left = (gray.right - gray.left - 640) / 2;
  162.                 r.bottom = r.top + 400;
  163.                 r.right = r.left + 640;
  164.                 InsetRect(&r, 1, 1);
  165.                 wp = NewWindow(&wr, &r, "\p", false, plainDBox, (WindowRef) -1, false, 237);
  166.                 SetPort(wp);
  167.                 SetWindowPic(wp, (PicHandle) gMacsBug);
  168.                 ShowHide(wp, true);
  169.                 DrawPicture((PicHandle) gMacsBug, &wp->portRect);
  170.                 for (;;) {
  171.                     GetNextEvent(keyDownMask, &xer);
  172.                     SetPort(wp);
  173.                     ir.left = 77;
  174.                     ir.right = 78;
  175.                     ir.top = 387;
  176.                     ir.bottom = 396;
  177.                     StdRect(kQDGrafVerbInvert, &ir);
  178.                     if (!gInMenuSelect) break;
  179.             //        if (xer.what == keyDown && '\r' == (char) xer.message) break;
  180.                 }
  181.                 SetWindowPic(wp, (PicHandle) 0);
  182.                 CloseWindow(wp);
  183.             }
  184.         }
  185.         SetPort(oldPort);
  186.     }
  187.  
  188.     SetA4(oldA4);
  189. }
  190.  
  191. asm void GNEFilterGlue(void)
  192.     {
  193.     machine    68020
  194.     CLR.L    -(A7)
  195.     MOVEM.L    D0-D7/A0-A6,-(A7)
  196.     JSR        SetCurrentA4
  197.     MOVE.L    gFilterProc,60(A7)
  198.     TST.W    gGNEReEntrancy
  199.     BNE        @ReEntrancyDetected
  200.     TST.W    (A1)
  201.     BNE.S    @RealEvent
  202.     ST.B    gGNEReEntrancy
  203.     BSR.S    @DispatchToMenuSelectingThread
  204. @ReturnFromMenuSelect:
  205.     CLR.W    gGNEReEntrancy
  206.     TST.W    gHaveFakeMSResult
  207.     MOVE.L    gGNEPort,A6
  208.     BEQ.S    @Return
  209.     MOVEM.L    (A7)+,D0-D7/A0-A3
  210.     MOVE.W    #mouseDown,0(A1) // EventRecord.what(A1)
  211.     MOVE.L    #0x00020037,10(A1) // EventRecord.where(A1)
  212.     MOVE.W    #0x0101,D0
  213.     MOVEM.L    (A7)+,A4-A5
  214.     MOVE.W    D0,12(A7)
  215.     BRA.S    @RestoreGNEPort
  216.  
  217. @DispatchToMenuSelectingThread:
  218.     MOVE.L    (A7)+,gGNEPC
  219.     MOVE.L    A7,gGNEStack
  220.     MOVE.L    (A5),A0
  221.     MOVE.L    (A0),gGNEPort
  222.     MOVE.L    0x110,0xF0
  223.     CLR.L    0x110
  224.     MOVE.L    gMenuSelectStack,A7
  225.     MOVE.L    gMenuSelectPC,-(A7)
  226.     RTS
  227.  
  228. @RealEvent:
  229.     CMP.W    #mouseDown,0(A1)    // EventRecord.what(A1)
  230.     BNE        @Exit
  231.     TST.W    gInMenuSelect
  232.     BEQ        @Exit
  233.     ST.B    gGNEReEntrancy
  234. @Lock:
  235.     BSR.S    @DispatchToMenuSelectingThread
  236.  
  237.     TST.W    gInMenuSelect
  238.     BEQ.S    @ReturnFromMenuSelect
  239.     BRA.S    @Lock
  240.  
  241. @Return:
  242.     MOVEM.L    (A7)+,D0-D7/A0-A5
  243. @RestoreGNEPort:
  244.     MOVE.L    A0,-(A7)
  245.     MOVE.L    (A5),A0
  246.     MOVE.L    A6,(A0)
  247.     MOVE.L    (A7)+,A0
  248.     MOVE.L    (A7)+,A6
  249.     RTS
  250.  
  251. @Exit:
  252. @ReEntrancyDetected:
  253.     MOVEM.L    (A7)+,D0-D7/A0-A6
  254.     CMP.W    #keyDown,0(A1)
  255.     BNE.S    @notMacsBug
  256.     MOVEM.L    A0-A3/D0-D3,-(A7)
  257.     LINK    A6,#0
  258.     MOVE.L    A1,-(A7)
  259.     JSR        DoMacsBugThing
  260.     UNLK    A6
  261.     MOVEM.L    (A7)+,A0-A3/D0-D3
  262. @notMacsBug:
  263.     RTS
  264.     }
  265.  
  266. static asm void YieldToTheAppAndHopeItDoesntCallMenuSelectAgain(void)
  267. {
  268.     MOVEM.L    D0-D7/A0-A6,-(A7)
  269.     MOVE.L    A7,gMenuSelectStack
  270.     MOVE.L    0xF0,0x110
  271.     PEA        @Return
  272.     MOVE.L    (A7)+,gMenuSelectPC
  273.     MOVE.L    (A5),A0
  274.     MOVE.L    (A0),gMenuSelectPort
  275.     MOVE.L    gGNEStack,A7
  276.     MOVE.L    gGNEPC,-(A7)
  277.     RTS
  278.  
  279. @Return:
  280.     MOVEM.L    (A7)+,D0-D7/A0-A6
  281.     MOVE.L    A0,-(A7)
  282.     MOVE.L    (A5),A0
  283.     MOVE.L    gMenuSelectPort,(A0)
  284.     MOVE.L    (A7)+,A0
  285.     RTS
  286. }
  287.  
  288. static void ShowHideScreen(Boolean show)
  289.     {
  290.     static Ptr sRealBase;
  291.     PixMapHandle devicePixMap;
  292.     
  293.     devicePixMap = (*GetMainDevice())->gdPMap;
  294.     
  295.     if (!show)
  296.         {
  297.         sRealBase = (*devicePixMap)->baseAddr;
  298.         (*devicePixMap)->baseAddr = LMGetROMBase() + 1024;
  299.         }
  300.     else
  301.         {
  302.         (*devicePixMap)->baseAddr = sRealBase;
  303.         }
  304.     }
  305.     
  306. static Rect sLastWinRect = { 0 };
  307. static RgnHandle sLastGrayRgn = NULL;
  308. static int sDoPaint = false;
  309.  
  310. static UniversalProcPtr gOldEraseRectAddress;
  311. static UniversalProcPtr gOldEraseRgnAddress;
  312.  
  313. static void RestoreGrayRgn(RgnHandle clipRgn)
  314.     {
  315.     WindowPtr    blastWindow;
  316.     Rect winRect = sLastWinRect;
  317.     RgnHandle    clobberedRgn;
  318.     GrafPtr        currentPort;
  319.         
  320.     winRect.bottom += 2;
  321.     winRect.right += 2;
  322.     winRect.left -= 1;
  323.     
  324.     // Pad the rect out so it covers alignment for menu saving
  325.     
  326.     InsetRect(&winRect, -3, -3);
  327.     
  328.     CopyRgn(sLastGrayRgn, GetGrayRgn());
  329.     DisposeRgn(sLastGrayRgn);
  330.     sLastGrayRgn = NULL;
  331.     
  332.     clobberedRgn = NewRgn();
  333.     RectRgn(clobberedRgn, &winRect);
  334.     
  335.     // Restore the window regions
  336.     CalcVisBehind(FrontWindow(), clobberedRgn);
  337.     
  338.     // Carve out any new clip
  339.     
  340.     if (clipRgn)
  341.         {
  342.         sLastGrayRgn = NewRgn();
  343.         CopyRgn(GetGrayRgn(), sLastGrayRgn);
  344.         
  345.         DiffRgn(GetGrayRgn(), clipRgn, GetGrayRgn());
  346.         CalcVisBehind(FrontWindow(), clipRgn);
  347.         }
  348.     
  349.     if (sDoPaint)
  350.         {
  351.         if (clipRgn)
  352.             {
  353.             Rect clipRect = (*clipRgn)->rgnBBox;
  354.             
  355.             if (SectRect(&clipRect, &winRect, &clipRect))
  356.                 sDoPaint = false;
  357.             }
  358.         else
  359.             {
  360.             sDoPaint = false;
  361.             }
  362.             
  363.         GetPort(¤tPort);
  364.         PaintBehind(FrontWindow(), clobberedRgn);
  365.         SetPort(currentPort);
  366.         }
  367.     
  368.     CalcVisBehind(FrontWindow(), clobberedRgn);
  369.     
  370.     // ShowHideScreen(false);
  371.     
  372.     // Generate the update and clear the hole
  373.         
  374.     #if 0
  375.     blastWindow = NewCWindow(NULL, &winRect, "\p", false, altDBoxProc, (WindowPtr)-1, false, 0);
  376.     ShowHide(blastWindow, true);
  377.     DisposeWindow(blastWindow);
  378.     #endif
  379.     
  380.     // ShowHideScreen(true);
  381.     }
  382.  
  383. static void BlastAndYield(void)
  384.     {
  385.     static sLastBlast = 0;
  386.     
  387.     CGrafPtr winPort;
  388.     Rect winRect;
  389.     Rect grayRect;
  390.     Rect tempRect;
  391.     RgnHandle menuRgn = NULL;
  392.     WindowPtr blastWindow;
  393.     Boolean doUpdate;
  394.     
  395.     long time = TickCount();
  396.     
  397.     if (time < sLastBlast + 10)
  398.         return;
  399.         
  400.     sLastBlast = time;
  401.     
  402.     GetCWMgrPort(&winPort);
  403.     
  404.     winRect = (*winPort->clipRgn)->rgnBBox;
  405.     grayRect = (*GetGrayRgn())->rgnBBox;
  406.     
  407.     SectRect(&winRect, &grayRect, &tempRect);
  408.     
  409.     doUpdate = !EmptyRect(&winRect) && !EqualRect(&winRect, &sLastWinRect) && !EqualRect(&grayRect, &tempRect);
  410.     
  411.     if (doUpdate)
  412.         {
  413.         Rect tempLast = winRect;
  414.         
  415.         winRect.bottom += 2;
  416.         winRect.right += 2;
  417.         winRect.left -= 1;
  418.         
  419.         menuRgn = NewRgn();
  420.         RectRgn(menuRgn, &winRect);
  421.         
  422.         if (sLastGrayRgn)
  423.             {
  424.             RestoreGrayRgn(menuRgn);
  425.             }
  426.         else
  427.             {
  428.             sLastGrayRgn = NewRgn();
  429.             CopyRgn(GetGrayRgn(), sLastGrayRgn);
  430.             
  431.             DiffRgn(GetGrayRgn(), menuRgn, GetGrayRgn());
  432.             CalcVisBehind(FrontWindow(), menuRgn);
  433.             }
  434.             
  435.         DisposeRgn(menuRgn);
  436.         
  437.         sLastWinRect = tempLast;
  438.         
  439.         #if 0
  440.         sLastWinRect = winRect;
  441.         
  442.         winRect.bottom += 2;
  443.         winRect.right += 2;
  444.         winRect.left -= 1;
  445.     
  446.         sLastGrayRgn = NewRgn();
  447.         CopyRgn(GetGrayRgn(), sLastGrayRgn);
  448.         
  449.         menuRgn = NewRgn();
  450.         RectRgn(menuRgn, &winRect);
  451.         
  452.         DiffRgn(GetGrayRgn(), menuRgn, GetGrayRgn());
  453.         
  454.         #if 0
  455.         
  456.         ShowHideScreen(false);
  457.         
  458.         // We blast the gray rgn for minimal possible bug generate an update for the area
  459.         // restored by the menu manager.
  460.                 
  461.         blastWindow = NewCWindow(NULL, &winRect, "\p", false, altDBoxProc, (WindowPtr)-1, false, 0);
  462.         ShowHide(blastWindow, true);
  463.         DisposeWindow(blastWindow);
  464.         
  465.         ShowHideScreen(true);
  466.         #endif
  467.         
  468.         CalcVisBehind(FrontWindow(), menuRgn);
  469.         DisposeRgn(menuRgn);
  470.         #endif
  471.         }
  472.     
  473.     YieldToTheAppAndHopeItDoesntCallMenuSelectAgain();
  474.     }
  475.  
  476. RGBColor    white = {-1, -1, -1};
  477.  
  478. pascal short myWaitMouseUp(void)
  479. {
  480.         // Set up A4, so we can access our globals.
  481.     long        oldA4;
  482.     short        result;
  483.     long        temp;
  484.     short        menuID, menuItem;
  485.     short        menuModifiers;
  486.     MenuHandle    mh;
  487.     EventRecord    keyEvent;
  488.     UniversalProcPtr patchedEraseRectAddress;
  489.     UniversalProcPtr patchedEraseRgnAddress;
  490.     RGBColor    oldBack;
  491.  
  492.     oldA4 = SetCurrentA4();
  493.  
  494.     patchedEraseRectAddress = GetToolTrapAddress(0xA8A3);
  495.     patchedEraseRgnAddress = GetToolTrapAddress(0xA8D4);
  496.     SetToolTrapAddress(gOldEraseRectAddress, 0xA8A3);
  497.     SetToolTrapAddress(gOldEraseRgnAddress, 0xA8D4);
  498.     GetBackColor(&oldBack);
  499.     RGBBackColor(&white);
  500.     BlastAndYield();
  501.     RGBBackColor(&oldBack);
  502.     SetToolTrapAddress(patchedEraseRectAddress, 0xA8A3);
  503.     SetToolTrapAddress(patchedEraseRgnAddress, 0xA8D4);
  504.  
  505.         // Call the old WaitMouseUp:
  506. #ifndef powerc
  507.     result = gOldWaitMouseUp();
  508. #else
  509.     result = CallUniversalProc((UniversalProcPtr)gOldWaitMouseUp, uppWaitMouseUpProcInfo);
  510. #endif
  511.  
  512.         // And restore the value of A4 on the way out.
  513.     SetA4(oldA4);
  514.  
  515.     return result;
  516. }
  517.  
  518. #if 0
  519.  
  520. static Rect gLastMenuRect = {0, 0, 0, 0};
  521. static void* gOldMBarHook;
  522.  
  523. static asm void myMBarHook(void)
  524.     {
  525.     MOVEM.L    A4,-(SP)
  526.     JSR        SetCurrentA4
  527.     MOVE.L    8(SP),A0
  528.     MOVE.L    (A0)+,gLastMenuRect.top
  529.     MOVE.L    (A0),gLastMenuRect.bottom
  530.     TST.L    gOldMBarHook
  531.     MOVEQ    #0,D0
  532.     BEQ        @Exit
  533.     MOVE.L    gOldMBarHook,A0
  534.     MOVEM.L    (SP)+,A4
  535.     JMP        (A0)
  536.     
  537. @Exit
  538.     MOVEM.L    (SP)+,A4
  539.     RTD        #4
  540.     }
  541.     
  542. #endif
  543.  
  544. pascal void myDrawMenuBar(void)
  545.     {
  546.     long oldA4 = SetCurrentA4();
  547.     
  548.     if (!gInMenuSelect)
  549.         gOldDrawMenuBar();
  550.     
  551.     SetA4(oldA4);
  552.     }
  553.  
  554. pascal void myHiliteMenu(short menuID)
  555.     {
  556.     long    oldA4 = SetCurrentA4();
  557.     
  558.     if (!gInMenuSelect)
  559.         gOldHiliteMenu(menuID);
  560.     
  561.     SetA4(oldA4);
  562.     }
  563.     
  564. pascal void myJShieldCursor(short left, short top, short right, short bottom)
  565.     {
  566.     long    oldA4 = SetCurrentA4();
  567.     Rect    shieldRect;
  568.     Rect    bigLastRect;
  569.     
  570.     SetRect(&shieldRect, left, top, right, bottom);
  571.     bigLastRect = sLastWinRect;
  572.     InsetRect(&bigLastRect, -2, -2);
  573.     
  574.     if (gInMenuSelect && !gGNEReEntrancy && sLastGrayRgn && SectRect(&shieldRect, &bigLastRect, &shieldRect))
  575.         sDoPaint = true;
  576.         
  577.     gOldJShieldCursor(left, top, right, bottom);
  578.     
  579.     SetA4(oldA4);
  580.     }
  581.  
  582. void myMenuSelectLoopCode(void)
  583.     {
  584.     while (true)
  585.         {
  586.         if (gDoSelect)
  587.             {
  588.             
  589.             gDoSelect = false;
  590.  
  591.             gOldWaitMouseUp = (void *) GetToolTrapAddress(0xA977);
  592.             SetToolTrapAddress(NewRoutineDescriptor((ProcPtr) &myWaitMouseUp,uppWaitMouseUpProcInfo,kPowerPCISA), 0xA977);
  593.             
  594.             #if 0
  595.             gOldMBarHook = (void*)LMGetMBarHook();
  596.             LMSetMBarHook(myMBarHook);
  597.             
  598.             gLast
  599.             #endif
  600.             
  601.             SetRect(&sLastWinRect, 0, 0, 0, 0);
  602.             
  603.             gInMenuSelect = true;
  604.             gOldEraseRectAddress = GetToolTrapAddress(0xA8A3);
  605.             gOldEraseRgnAddress = GetToolTrapAddress(0xA8D4);
  606.             gFakeMSResult = gOldMenuSelect(gMSPoint);
  607.             gInMenuSelect = false;
  608.             
  609.             if (sLastGrayRgn)
  610.                 RestoreGrayRgn(0);
  611.             
  612.             //LMSetMBarHook(gOldMBarHook);
  613.             SetToolTrapAddress((ProcPtr) gOldWaitMouseUp, 0xA977);
  614.  
  615.             if ((gFakeMSResult & 0xFFFF0000) && (gFakeMSResult & 0xFFFF))
  616.                 gHaveFakeMSResult = true;
  617.             else
  618.                 gHaveFakeMSResult = false;
  619.             }
  620.         YieldToTheAppAndHopeItDoesntCallMenuSelectAgain();
  621.         }
  622.     }
  623.     
  624. pascal long myMenuSelect(Point pt)
  625. {
  626.         // Set up A4, so we can access our globals.
  627.     long    oldA4;
  628.     long    result;
  629.     int        oldState;
  630.  
  631.     oldA4 = SetCurrentA4();
  632.  
  633.     if (gHaveFakeMSResult)
  634.         {
  635.         gHaveFakeMSResult = false;
  636.         result = gFakeMSResult;
  637.         }
  638.     else if (StillDown())
  639.         {
  640.         gDoSelect = true;
  641.         gMSPoint = pt;
  642.         result = false;
  643.         }
  644.     else
  645.         {
  646.             // Call the old MenuSelect:
  647.     #ifndef powerc
  648.         result = gOldMenuSelect(pt);
  649.     #else
  650.         result = CallUniversalProc((UniversalProcPtr)gOldMenuSelect, uppMenuSelectProcInfo, pt);
  651.     #endif
  652.         }
  653.  
  654.  
  655.         // And restore the value of A4 on the way out.
  656.     SetA4(oldA4);
  657.  
  658.     return result;
  659. }
  660.